package com.lwy.setter;

import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;

/**
 * <br/>
 *
 * @author bukong
 * @date 2022/6/30
 */
@Slf4j
public class NameSetters {

    public static <T> List<T> fillNames(List<T> objects) {
        if (CollectionUtils.isEmpty(objects)) {
            return objects;
        }
        Class tClass = new ArrayList<T>(objects).get(0).getClass();
        try {
            // 找到class对应的注解列表
            final List<Class> annotationClasses = NameSetterMeta.getAnnotationClasses(tClass);
            objects.removeIf(Objects::isNull);

            annotationClasses.forEach(annotationClass -> {
                long start = System.currentTimeMillis();
                // 找到注解对应的setter
                final BaseNameSetter baseNameSetter = NameSetterMeta.ANNOTATION_SETTER_MAP.get(annotationClass);
                if (baseNameSetter == null) {
                    log.debug("NameSetter not found for annotation class: {}", annotationClass.getName());
                } else {
                    // 调用setter
                    if (baseNameSetter.isFillNameByCode()) {
                        baseNameSetter.fillNameByCode(objects, tClass);
                    } else {
                        baseNameSetter.fillNameById(objects, tClass);
                    }
                }
                log.debug("fillName , class = {}, annotation={}, cost={}ms", tClass.getName(), annotationClass.getName(), System.currentTimeMillis() - start);
            });
            // 内部属性填充
            for (Field field : tClass.getDeclaredFields()) {
                final Class fieldClass = field.getType();
                if (Collection.class.isAssignableFrom(fieldClass)) {
                    final Class collectionElementClz = getActualClassOfCollection(field);
                    if (collectionElementClz == null) {
                        continue;
                    }
                    if (NameSetterMeta.isClassNeedProcess(collectionElementClz)) {
                        field.setAccessible(true);
                        final List fieldList = new ArrayList<>();
                        for (T obj : objects) {
                            Object fieldVal = field.get(obj);
                            if(fieldVal!=null) {
                                fieldList.addAll((Collection) fieldVal);
                            }
                        }
                        fillNames(fieldList);
                    }
                } else if (NameSetterMeta.isClassNeedProcess(fieldClass)) {
                    field.setAccessible(true);
                    final List fieldList = new ArrayList<>();
                    for (T obj : objects) {
                        Object fieldVal = field.get(obj);
                        if(fieldVal!=null) {
                            fieldList.add(fieldVal);
                        }
                    }
                    fillNames(fieldList);
                }
            }
        } catch (Exception e) {

        }
        return objects;
    }

    private static Class getActualClassOfCollection(Field field) {
        if (!Collection.class.isAssignableFrom(field.getType())) {
            return null;
        }
        Type genericType = field.getGenericType();
        // 如果是泛型参数的类型
        if (genericType instanceof ParameterizedType) {
            ParameterizedType pt = (ParameterizedType) genericType;
            //得到泛型里的class类型对象
            return (Class<?>) pt.getActualTypeArguments()[0];
        }
        return null;
    }

    public static <T> T fillNames(T object) {
        if (object == null) {
            return null;
        }
        fillNames(Arrays.asList(object));
        return object;
    }

}
